﻿
#include <iostream>
#include <atomic>
#include <thread>
#include <mutex>
#include <unistd.h>
using namespace std;

//memory_order_relaxed,
//memory_order_consume,
//memory_order_acquire,
//memory_order_release,
//memory_order_acq_rel,
//memory_order_seq_cst
void test_fence()
{
    atomic_thread_fence(memory_order_relaxed);
    atomic_thread_fence(memory_order_consume);
    atomic_thread_fence(memory_order_acquire);
    atomic_thread_fence(memory_order_release);
    atomic_thread_fence(memory_order_acq_rel);
    atomic_thread_fence(memory_order_seq_cst);
}
#ifndef WINDOWS
volatile int g_a = 0;
volatile int l = 0;

#define READ_XXX(x,memorder) \
    ({ \
        atomic_thread_fence(memorder); \
        x; \
     })

#define READ_RELAXED(x)     READ_XXX(x,memory_order_relaxed)
#define READ_CONSUME(x)     READ_XXX(x,memory_order_consume)
#define READ_ACQUIRE(x)     READ_XXX(x,memory_order_acquire)
#define READ_SEQ_CST(x)     READ_XXX(x,memory_order_seq_cst)

void test_read_fence() {
    l = READ_RELAXED(g_a);
    l = READ_CONSUME(g_a);
    l = READ_ACQUIRE(g_a);
    l = READ_SEQ_CST(g_a);
}

#define WRITE_XXX(x,val,memorder) \
    ({ \
        atomic_thread_fence(memorder); \
        x = val; \
     })

#define WRITE_RELAXED(x,val)     WRITE_XXX(x,val,memory_order_relaxed)
#define WRITE_RELEASE(x,val)     WRITE_XXX(x,val,memory_order_release)
#define WRITE_SEQ_CST(x,val)     WRITE_XXX(x,val,memory_order_seq_cst)

void test_write_fence()
{
    WRITE_RELAXED(g_a, l);
    WRITE_RELEASE(g_a, l);
    WRITE_SEQ_CST(g_a, l);
}
#endif

atomic<int> aa;
volatile int bb = 0;
void test_atomic()
{
    bb = aa.load(memory_order_relaxed);
    bb = aa.load(memory_order_consume);
    bb = aa.load(memory_order_acquire);
    bb = aa.load(memory_order_seq_cst);

    aa.store(bb, memory_order_relaxed);
    aa.store(bb, memory_order_release);
    aa.store(bb, memory_order_seq_cst);

    aa+=10;
    aa -= 10;
}

std::mutex g_lock;

void test_no_race()
{
    for(int i = 0;i < 10;++i)
    {
        g_lock.lock();
        usleep(100*1000);
        g_lock.unlock();
    }
}

void test_race()
{
    std::thread t1(test_no_race);
    std::thread t2(test_no_race);
    
    t1.join();
    t2.join();
}
int main()
{
    printf("test begin\n");
    //test_no_race();
    test_race();


    //test_atomic();
    //test_read_fence();
    //test_write_fence();
    return 0;
}


